--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--[[

    长矛冲刺的伤害模块

    半径为1的横扫距离

]]--
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---
    local SEARCH_WIDTH = 2
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- 目标扫描TAGS
    local BOUNCE_MUST_TAGS = { "_combat" }
    local BOUNCE_NO_TAGS = { "INLIMBO", "wall", "notarget", "player", "companion", "flight", "invisible", "noattack", "hiding" } -- "player", "companion", "flight", "invisible", "noattack", "hiding"
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- buff weapon 创建虚构武器，比如 冰魔杖、火魔杖
    local hidden_weapons = {}
    local function GetHiddenWeapon(player,prefab)
        hidden_weapons[player] = hidden_weapons[player] or {}
        local weapon = hidden_weapons[player][prefab]
        if weapon and weapon:IsValid() then
            return weapon
        end
        weapon = player:SpawnChild(prefab)
        weapon:Hide()
        weapon.Transform:SetPosition(0,100,0)
        if weapon.Physics then
            weapon.Physics:Teleport(0,100,0)
            weapon.Physics:Stop()
        end
        if weapon.components.finiteuses then -- 屏蔽耐久
            weapon.components.finiteuses.Use = function() end
        end
        weapon:AddTag("INLIMBO")
        weapon:AddTag("NOCLICK")
        weapon:AddTag("NOBLOCK")
        weapon:AddTag("hutao_spell_hidden_weapon")
        weapon:DoTaskInTime(5,weapon.Remove)
        hidden_weapons[player][prefab] = weapon
        return weapon
    end
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- 单个武器类型的伤害执行函数
    --------------------------------------------------------------------------------------------
    --- 缺省基础
        local function default_damage_fn(player,target,weapon)
            local damage_mult = player.components.hutao_com_polearm_mastery:GetSpikeModifier() * player.components.combat.externaldamagemultipliers:Get()
            local damage , sp_damage = weapon.components.weapon:GetDamage(player,target)
            damage = damage * damage_mult -- 长矛冲刺伤害翻倍
            if (damage or 0) <= 0 then
                return
            end
            if type(sp_damage) == "table" then -- 类型伤害也翻倍(位面伤害/阵营伤害)
                for k, v in pairs(sp_damage) do
                    sp_damage[k] = v * damage_mult
                end
            end
            target.components.combat:GetAttacked(player, damage, weapon, nil, sp_damage)
            -- if weapon.components.finiteuses then -- 3 次耐久消耗
            --     weapon.components.finiteuses:Use(3)
            -- end
        end
    --------------------------------------------------------------------------------------------
    --- 长矛
        local function do_damage_fn_spear(player,target,weapon)
            --[[
                长矛：胡桃最熟悉的武器，精湛的枪技可以轻松格开敌人的攻势。
                突刺命中敌人时，会令胡桃获得70%的减伤，持续7*(1+a)秒，a为胡桃的体力系数a。
                持续期间内长矛突刺命中敌人会令持续时间重置。
            ]]--
            default_damage_fn(player,target,weapon)
            local test_num = 100
            local debuff_inst = nil
            local debuff_prefab = "hutao_debuff_polearm_mastery_spear"
            local debuff_remain_time = ( player.components.hutao_com_physical_power:GetModulus() + 1 )*7
            if debuff_remain_time <= 0 then
                return
            end
            -- 上debuff 并配置时间
            while test_num > 0 do
                debuff_inst = player:GetDebuff(debuff_prefab)
                if debuff_inst and debuff_inst:IsValid() then
                    break
                end
                player:AddDebuff(debuff_prefab,debuff_prefab)
                test_num = test_num - 1
            end
            if debuff_inst then
                debuff_inst:PushEvent("SetTime",debuff_remain_time)
            end
        end
    --------------------------------------------------------------------------------------------
    --- 冰魔杖
        local function do_damage_fn_icestaff(player,target,weapon)
            default_damage_fn(player,target,weapon)
            local icestaff = GetHiddenWeapon(player,"icestaff")
            local onattack_blue = icestaff.components.weapon.onattack
            if onattack_blue then
                for i = 1, 3, 1 do
                    onattack_blue(weapon, player, target, true)
                end
            end
        end
    --------------------------------------------------------------------------------------------
    --- 火魔杖
        local function do_damage_fn_firestaff(player,target,weapon)
            local has_debuff,debuff_inst = player.components.hutao_com_blood_plum_scent_for_player:HasDebuff(target)
            if has_debuff and debuff_inst then
                debuff_inst.components.hutao_com_blood_plum_scent_for_debuff:ResetRemainTime()                
            end
            SpawnPrefab("hutao_sfx_pink_flame"):PushEvent("Set",{target = target})
        end
    --------------------------------------------------------------------------------------------
    --- 雨伞
        local function do_damage_fn_umbrella(player,target,weapon)
            --[[
                雨伞：突刺命中敌人后胡桃获得91%防水值，持续7*(1+a)秒。
            ]]--
            default_damage_fn(player,target,weapon)
            local test_num = 100
            local debuff_inst = nil
            local debuff_prefab = "hutao_debuff_polearm_mastery_umbrella"
            local debuff_remain_time = (player.components.hutao_com_physical_power:GetModulus()+1)*7
            if debuff_remain_time <= 0 then
                return
            end
            -- 上debuff 并配置时间
            while test_num > 0 do
                debuff_inst = player:GetDebuff(debuff_prefab)
                if debuff_inst and debuff_inst:IsValid() then
                    break
                end
                player:AddDebuff(debuff_prefab,debuff_prefab)
                test_num = test_num - 1
            end
            if debuff_inst then
                debuff_inst:PushEvent("SetTime",debuff_remain_time)
            end
        end
    --------------------------------------------------------------------------------------------

    local PolearmPrefabs = {
        ---------------------------------------------------
        --- 缺省状态
            ["default"] = function(player,target,weapon)
                default_damage_fn(player,target,weapon)
            end,
        ---------------------------------------------------
        --- 长矛
            ["spear"] = do_damage_fn_spear,               -- 长矛
            ["spear_wathgrithr"] = do_damage_fn_spear,    -- 战斗长矛
        ---------------------------------------------------
        -- ["shovel"] = true,              -- 铲子
        -- ["goldenshovel"] = true,        -- 金铲子
        -- -- ["pitchfork"] = true,           -- 草叉 
        -- -- ["goldenpitchfork"] = true,     -- 金草叉
        -- ["trident"] = true,             -- 三叉戟   
        -- ["firestaff"] = true,           -- 火魔杖
        ["icestaff"] = do_damage_fn_icestaff,            -- 冰魔杖
        -- ["telestaff"] = true,           -- 传送法杖
        -- ["nightstick"] = true,          -- 晨星锤
        ["grass_umbrella"] = do_damage_fn_umbrella,      -- 雨伞
        ["umbrella"] = do_damage_fn_umbrella,            -- 雨伞
        ["voidcloth_umbrella"] = do_damage_fn_umbrella,  -- 雨伞
        -- ["shovel_lunarplant"] = true,   -- 亮茄锄铲
    }
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- 突刺路线上的 技能执行。
    local function GetWeapon(inst)
        local weapon = inst.replica.combat:GetWeapon() or inst.replica.inventory:GetEquippedItem(EQUIPSLOTS.HANDS)        
        return weapon
    end
    local function do_damage(inst,targets)
        local weapon = GetWeapon(inst)
        local weapon_prefab = weapon and weapon.prefab or "default"
        local damage_fn = inst.components.hutao_com_polearm_mastery:GetSpikeDamageFn(weapon_prefab)
        --------------------------------------------------------------------------------
        --- 伤害计算
            damage_fn = damage_fn or default_damage_fn
            for i, temp_target in ipairs(targets) do
                local temp_weapon = GetWeapon(inst)
                if temp_weapon and temp_weapon:IsValid() then
                    temp_weapon:AddTag("hutao_tag.polearm_spike_casting") -- 给武器上标签
                    damage_fn(inst,temp_target,temp_weapon)
                    temp_weapon:RemoveTag("hutao_tag.polearm_spike_casting") -- 移除武器标签
                end
            end
        --------------------------------------------------------------------------------
        --- 耐久消耗。每个怪物消耗 3 点耐久 。能造成伤害的才算数
            if #targets > 0 then
                weapon = GetWeapon(inst)
                if weapon and weapon:IsValid() and weapon.components.finiteuses
                    and weapon.components.weapon and weapon.components.weapon.damage > 0 then
                    weapon.components.finiteuses:Use(3*#targets)
                end
            end
        --------------------------------------------------------------------------------
        --[[
                此外，在【彼岸蝶舞】状态下，长柄突刺每次命中目标，会对目标附加持续10秒的【血梅香】效果。
                若目标身上已经有【血梅香】，会刷新持续时间至10秒但不会额外触发【血梅香】的伤害。
            ]]
            if #targets > 0 and inst.components.hutao_com_butterfly_s_embrace:IsActiving() then
                for k, temp_target in pairs(targets) do
                    if temp_target and temp_target.components.health and not temp_target.components.health:IsDead() then
                        local debuff_inst = inst.components.hutao_com_blood_plum_scent_for_player:GetTargetDebuff(temp_target)
                        debuff_inst.components.hutao_com_blood_plum_scent_for_debuff:ResetRemainTime()
                    end
                end                
            end
        --------------------------------------------------------------------------------
    end
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- 突刺路线 扫描路线上的目标函数
    local function spike_line_target_search_fn(inst,start_pos,end_pos)
        ------------------------------------------------------------------
        --- 以0.4距离为间隔，进行路线上的所有坐标的检测
        --- 使用归一化的向量，进行检测
            local points = {}
            -- 归一化方向向量
            local Normalize_Vect = (end_pos - start_pos):Normalize()        
            -- 计算两点之间的距离
            local total_distance = (end_pos - start_pos):Length()
            -- 计算每个点之间的距离
            local distance = 0.4
            -- 计算需要检测的点的数量
            local point_count = math.floor(total_distance / distance)
            -- 计算每个点之间的距离
            local distance_per_point = total_distance / point_count
            -- 计算每个点之间的归一化向量
            local point_vect = Normalize_Vect * distance_per_point
            -- 计算每个点之间的归一化向量
            for i = 0, point_count do
                -- 计算每个点之间的归一化向量
                local point = start_pos + point_vect * i
                -- 计算每个点之间的归一化向量
                table.insert(points, point)
            end
        ------------------------------------------------------------------
        --- 寻找合适的目标
            local targets_with_distance = {}
            for _,temp_pt in ipairs(points) do
                local ents = TheSim:FindEntities(temp_pt.x,0, temp_pt.z,SEARCH_WIDTH, BOUNCE_MUST_TAGS, BOUNCE_NO_TAGS, nil)
                for _,temp_target in ipairs(ents) do
                    if temp_target and temp_target:IsValid() and temp_target.components.health and not temp_target.components.health:IsDead() then
                        targets_with_distance[temp_target] = temp_target:GetDistanceSqToPoint(start_pos.x,0,start_pos.z)
                    end
                end                
            end            
        ------------------------------------------------------------------
        --- 重新排列并按照距离从近到远排列
            local targets = {}
            for target, distance in pairs(targets_with_distance) do
                table.insert(targets, target)
            end
            table.sort(targets, function(a, b) return targets_with_distance[a] < targets_with_distance[b] end)
        ------------------------------------------------------------------
        ---
            -- if #targets > 0 then
            --     -- do_damage(inst,targets)
            --     inst.components.hutao_com_polearm_mastery:DoSpikeCastingDamage(targets)
            -- end
        ------------------------------------------------------------------
        ---
            return targets
        ------------------------------------------------------------------
    end
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

return function(inst)
    if not TheWorld.ismastersim then
        return
    end
    --------------------------------------------------------------------------------------------------------------------------------------------------------
    --- 配置伤害函数。
        inst.components.hutao_com_polearm_mastery:AddSpikeDamageFn("default",default_damage_fn)                     --- 缺省状态
        inst.components.hutao_com_polearm_mastery:AddSpikeDamageFn("spear",do_damage_fn_spear)                      --- 长矛
        inst.components.hutao_com_polearm_mastery:AddSpikeDamageFn("spear_wathgrithr",do_damage_fn_spear)           --- 战斗长矛

        inst.components.hutao_com_polearm_mastery:AddSpikeDamageFn("icestaff",do_damage_fn_icestaff)                --- 冰魔杖
        inst.components.hutao_com_polearm_mastery:AddSpikeDamageFn("firestaff",do_damage_fn_firestaff)              --- 火魔杖

        inst.components.hutao_com_polearm_mastery:AddSpikeDamageFn("grass_umbrella",do_damage_fn_umbrella)          --- 草雨伞
        inst.components.hutao_com_polearm_mastery:AddSpikeDamageFn("umbrella",do_damage_fn_umbrella)                --- 雨伞
        inst.components.hutao_com_polearm_mastery:AddSpikeDamageFn("voidcloth_umbrella",do_damage_fn_umbrella)      --- 暗影雨伞
    --------------------------------------------------------------------------------------------------------------------------------------------------------
    --- 配置冲锋路线上的伤害函数
        inst.components.hutao_com_polearm_mastery:SetSpikeCastingDamageFn(do_damage)        --- 对目标造成伤害的函数
        inst.components.hutao_com_polearm_mastery:SetSpikeLineTargetSearchFn(spike_line_target_search_fn) --- 寻找路线上的目标函数
    --------------------------------------------------------------------------------------------------------------------------------------------------------
    --- 造成伤害的入口。【笔记】暂时废弃这个入口，通过 hutao_com_polearm_mastery 执行。
        -- inst:ListenForEvent("hutao_event.polearm_mastery.do_damage",function(inst,_table)
        --     local start_pos = _table.start_pos
        --     local end_pos = _table.end_pos
        --     local targets = inst.components.hutao_com_polearm_mastery:DoSpikeLineTargetSearch(start_pos,end_pos) or {}
        --     if #targets > 0 then
        --         inst.components.hutao_com_polearm_mastery:DoSpikeCastingDamage(targets)
        --     end
        -- end)
    --------------------------------------------------------------------------------------------------------------------------------------------------------
end